/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utility;

import java.util.Calendar;
import java.util.Date;

/**
 *
 * @author daolam
 */
public class MTGuid {
    private static int seedID = 0;
    private static Date lastTime = Calendar.getInstance().getTime();
    private static byte serverKey;
    private static int maxSeedPerSecond = 0x1FFFFFF;
    private static Object syncObj = new Object();

    public void setServerKey(byte key)
    {
        serverKey = key;
    }
    
    public static long newGuid() throws InterruptedException
    {
            return createGuidID(serverKey);
    }
		
    private static long createGuidID(byte serverKey) throws InterruptedException
    {
        synchronized (syncObj)
        {
            seedID++;

            if (seedID > maxSeedPerSecond)
            {
                    Date current = Calendar.getInstance().getTime();
                    int elapsedTime = current.getSeconds() - lastTime.getSeconds();
                    if (elapsedTime < 1)
                    {
                        Thread.sleep(1001 - elapsedTime*1000);
                        current = Calendar.getInstance().getTime();
                    }
                    lastTime = current;
                    seedID = 1;
            }

            long guid = (long)seedID;                           // bits: 00->24 (use 25 bit for seed) = 32 milion id per second per server
            guid |= (long)serverKey << 25 |                     // bits: 25->32	(use 8 bits for server key)
                    (long)lastTime.getSeconds() << 33 |         // bits: 33->38	(use 6 bits for seconds)
                    (long)lastTime.getMinutes() << 39 |         // bits: 39->44 (use 6 bits for minutes)
                    (long)lastTime.getHours() << 45 |           // bits: 45->49 (use 5 bits for hours)
                    (long)lastTime.getDay() << 50 |             // bits: 50->54 (use 5 bits for days)
                    (long)lastTime.getMonth() << 55 |           // bits: 55->58 (use 4 bits for month)
                    (long)(lastTime.getYear() - 2011) << 59;    // bits: 59->63	(use 5 bits for years) = 32 years

            return guid;
        }
    }
}
